/* 
 * File:   QualityMeasurerTT.cpp
 * Author: Guilherme Monteiro
 * 
 */

#include "../headers/QualityMeasurerTT.h"

QualityMeasurerTT::QualityMeasurerTT() {
}

QualityMeasurerTT::QualityMeasurerTT(const QualityMeasurerTT& orig) {
}

QualityMeasurerTT::~QualityMeasurerTT() {
}

/**
 * 
 */
void QualityMeasurerTT::run() {
    //    vector<string> bookNames = getBookNames();
    vector<string> bookNames;
    bookNames.push_back("anuario1916pb");

    printf("bookNames.size: %d\n", (int) bookNames.size());

    writeHeaderOutputFile();

    vector<string>::iterator itBooks;
    for (itBooks = bookNames.begin(); itBooks != bookNames.end(); itBooks++) {
        vector<string> softAnswersPaths = getSoftAnswersPaths(*itBooks);
        vector<string> userAnswersPaths = getUserAnswersPaths(*itBooks);

        vector< pair<string, string> > pairs_tsoft_tuser = loadPairs(softAnswersPaths, userAnswersPaths);

        //        if(userAnswersPaths.size() != softAnswersPaths.size()) {
        //            throw CompatibilityAnswersException();
        //        }

        printf("userAnswersPaths.size: %d\n", (int) userAnswersPaths.size());
        printf("softAnswersPaths.size: %d\n", (int) softAnswersPaths.size());
        printf("pairs_tsoft_tuser.size: %d\n", (int) pairs_tsoft_tuser.size());

        printf("===============\n");

        vector< pair<string, string> >::iterator itPairs;
        for (itPairs = pairs_tsoft_tuser.begin(); itPairs != pairs_tsoft_tuser.end();
                itPairs++) {

            printf("userAnsPath: %s\n", (*itPairs).first.c_str());
            printf("softAnsPath: %s\n", (*itPairs).second.c_str());

            MetricsVectorTT* vec;
            if (strcmp("", (*itPairs).first.c_str()) != 0 && strcmp("", (*itPairs).second.c_str()) != 0) {
                vec = new MetricsVectorTT((*itPairs).first, (*itPairs).second);
            }

            writeFile(vec);
        }
    }
}

/**
 * Load pairs of software answers and user answers correspondents. The content
 * of the pairs is the correspondents paths to the files.
 * 
 * @param softAnsPaths: software answers paths vector
 *   Example of softAnsPath: x/saida/imageX_modelY.txt
 * @param userAnsPaths: user answers paths vector
 *   Example of userAnsPath: x/respostaUsuarioTT/imageX_Z.txt ==> Z indicates the table to be load from softAns file
 * @return pairs
 */
vector< pair<string, string> > QualityMeasurerTT::loadPairs(vector<string> softAnsPaths,
        vector<string> userAnsPaths) {

    vector< pair<string, string> > pairs;
    vector<string>::iterator itUserAnsPaths;

    for (itUserAnsPaths = userAnsPaths.begin(); itUserAnsPaths != userAnsPaths.end(); itUserAnsPaths++) {
        int indexOfCorrespondentAnswer = getIndexOfCorrespondentAnswer(*itUserAnsPaths, softAnsPaths);

        if (indexOfCorrespondentAnswer != -1) {
            pair<string, string> p;
            p.first = *itUserAnsPaths;
            p.second = softAnsPaths[indexOfCorrespondentAnswer];

            pairs.push_back(p);
        }
    }

    return pairs;
}

/**
 * Return index of correspondent software answer path in vector of software answers paths.
 * Return -1 if there is not a correspondent path.
 * 
 * @param uAnswerPath
 * @param softAnswersPaths
 * @return index
 */
int QualityMeasurerTT::getIndexOfCorrespondentAnswer(string uAnswerPath,
        vector<string> sAnswersPaths) {

    int index = -1;
    string page = getPageName(uAnswerPath);
    printf("page: %s\n", page.c_str());
    for (int i = 0; i < sAnswersPaths.size(); i++) {
        size_t found = sAnswersPaths[i].find(page);
        if (found != string::npos) {
            index = i;
            printf("index: %d\n", index);
            break;
        }
    }
    return index;
}

/**
 * Get a list of the book that will be
 * analyzed.
 * 
 * @return vector of book names
 */
vector<string> QualityMeasurerTT::getBookNames() {
    vector<string> bookNames;

    DIR *dir;
    struct dirent *ent;
    if ((dir = opendir("../books/")) != NULL) {
        while ((ent = readdir(dir)) != NULL) {
            if (ent->d_name[0] != '.') {
                bookNames.push_back(ent->d_name);
                //      printf("%s\n", ent->d_name);
            }
        }
        closedir(dir);
    }
    //    else {
    //        perror("Could not open directory");
    //        exit(1);
    //    }

    return bookNames;
}

/**
 * Get a list of user answers paths relatives to one
 * determined book.
 * 
 * @param book: book name
 * 
 * @return vector of user answers paths
 */
vector<string> QualityMeasurerTT::getSoftAnswersPaths(string book) {
    vector<string> softAnswersPaths;

    DIR *dir;
    struct dirent *ent;
    string softAnsPath = "../books/" + book + "/metadados/saida/";
    if ((dir = opendir(softAnsPath.c_str())) != NULL) {
        while ((ent = readdir(dir)) != NULL) {
            if (ent->d_name[0] != '.') {
                softAnswersPaths.push_back(softAnsPath + string(ent->d_name));
                //            printf("%s\n", ent->d_name);
            }
        }
        closedir(dir);
    }
    //    else {
    //        perror("Could not open directory");
    //        exit(1);
    //    }

    return softAnswersPaths;
}

/**
 * Get a list of software (TT) answers paths relatives
 * to one determined book.
 * 
 * @param book: book name
 * @return vector of software answers paths
 */
vector<string> QualityMeasurerTT::getUserAnswersPaths(string book) {
    //    vector<string> userAnswersPaths;
    //
    //    string userAnsPath = "../books/" + book + "/metadados/respostaUsuarioTT/";
    //    vector<string>::iterator itSoftAnsPaths;
    //    for(itSoftAnsPaths = softAnsPaths.begin(); itSoftAnsPaths != softAnsPaths.end(); itSoftAnsPaths++) {    
    //        string page = getPageName(*itSoftAnsPaths);
    //        printf("userAnsPath: %s\n", (*itSoftAnsPaths).c_str());
    //        printf("softAnsPath: %s\n", (userAnsPath+page).c_str());
    //        printf("------------------------------------\n");
    //        
    //        userAnswersPaths.push_back(userAnsPath + page);
    //    }
    //    
    //    return userAnswersPaths;

    //------------------------------------------------------------------
    vector<string> userAnswersPaths;

    DIR *dir;
    struct dirent *ent;
    string userAnsPath = "../books/" + book + "/metadados/respostaUsuarioTT/";
    if ((dir = opendir(userAnsPath.c_str())) != NULL) {
        while ((ent = readdir(dir)) != NULL) {
            if (ent->d_name[0] != '.') {
                userAnswersPaths.push_back(userAnsPath + string(ent->d_name));
                //            printf("%s\n", ent->d_name);
            }
        }
        closedir(dir);
    }
    //    else {
    //        perror("Could not open directory");
    //        exit(1);
    //    }

    return userAnswersPaths;
}

/**
 * Return page name relative to a user answer path.
 * 
 * @param userAnsPath: user answer path
 * @return page_name.txt
 */
string QualityMeasurerTT::getPageName(string userAnsPath) {
    string pageName = "";
    string::iterator itUAns;
    for (itUAns = --find(userAnsPath.begin(), userAnsPath.end(), '_'); *itUAns != '/'; itUAns--) {
        pageName = *itUAns + pageName;
    }

    return pageName;
}

/**
 * Write header of output file.
 */
void QualityMeasurerTT::writeHeaderOutputFile() {
    this->file = new File(OUTPUT_FILE);
    this->file->writeHeader1(
            "U_ANS_PATH" + FIELD_SEPARATOR +
            "S_ANS_PATH" + FIELD_SEPARATOR +
            "CU" + FIELD_SEPARATOR +
            "CS" + FIELD_SEPARATOR +
            "TP" + FIELD_SEPARATOR +
            "FP" + FIELD_SEPARATOR +
            "pTP" + FIELD_SEPARATOR +
            "pFP");
}

/**
 * Analyzes the total true positive rate and total false positive rate,
 * based in qualityTuples vector, and write them in qualityAnalysis/qmtt.csv file.
 */
void QualityMeasurerTT::writeFile(MetricsVectorTT* vec) {
    std::ostringstream stream_uAnsPath;
    stream_uAnsPath << vec->getUAnsPath();
    
    std::ostringstream stream_sAnsPath;
    stream_sAnsPath << vec->getSAnsPath();
    
    std::ostringstream stream_num_cells_user;
    stream_num_cells_user << vec->getNumCellsUser();

    std::ostringstream stream_num_cells_soft;
    stream_num_cells_soft << vec->getNumCellsSoft();

    std::ostringstream stream_num_TP;
    stream_num_TP << vec->getTP();

    std::ostringstream stream_num_FP;
    stream_num_FP << vec->getFP();

    std::ostringstream stream_percent_TP;
    stream_percent_TP.precision(2);
    //stream_percent_TP << fixed;
    stream_percent_TP << vec->getTP() / vec->getNumCellsSoft() * 100;

    std::ostringstream stream_percent_FP;
    stream_percent_FP.precision(2);
    //stream_percent_FP << fixed;
    stream_percent_FP << vec->getFP() / vec->getNumCellsSoft() * 100;

    string str = stream_uAnsPath.str() + FIELD_SEPARATOR +
            stream_sAnsPath.str() + FIELD_SEPARATOR +
            stream_num_cells_user.str() + FIELD_SEPARATOR +
            stream_num_cells_soft.str() + FIELD_SEPARATOR +
            stream_num_TP.str() + FIELD_SEPARATOR +
            stream_num_FP.str() + FIELD_SEPARATOR +
            stream_percent_TP.str() + FIELD_SEPARATOR +
            stream_percent_FP.str();

    file->writeHeaderN(str);
}